#include <sys/stat.h>
#include <string.h>
#include <sys/types.h> 
#include <unistd.h>
#include <pwd.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <grp.h>
#include <dirent.h>
#include <sys/wait.h>

int Read(char *buffer);
void printf_type(mode_t perm)
{
	char *str = "";
	if(S_ISREG(perm))  str = "regular";
	else if(S_ISDIR(perm))  str = "directory";
	else if(S_ISCHR(perm))  str = "character special";
	else if(S_ISBLK(perm))  str = "block special";
	else if(S_ISFIFO(perm)) str = "fifo";
	else if(S_ISLNK(perm))  str = "symbolic link";
	else if(S_ISSOCK(perm)) str = "socket";
	else str = "unknown mode";
	printf("%s\t", str);
}

#define STR_SIZE sizeof("rwxrwxrwx")
void printf_perm(mode_t perm)
{
	char str[STR_SIZE];
	snprintf(str, STR_SIZE, "%c%c%c%c%c%c%c%c%c",
        (perm & S_IRUSR) ? 'r' : '-', (perm & S_IWUSR) ? 'w' : '-',
        (perm & S_IXUSR) ? 'x':'-',
        (perm & S_IRGRP) ? 'r' : '-', (perm & S_IWGRP) ? 'w' : '-',
        (perm & S_IXGRP) ?'x':'-',
        (perm & S_IROTH) ? 'r' : '-', (perm & S_IWOTH) ? 'w' : '-',
        (perm & S_IXOTH) ?'x':'-');
        printf("%s\t",str);
}

void printf_link(nlink_t nlink){
	printf("%ld\t",nlink);
}

void printf_usrname(uid_t uid){
	struct passwd *user;
	user= getpwuid(uid);
	printf("%s\t", user->pw_name);
}

void printf_grname(gid_t gid){
	struct group *group;
	group= getgrgid(gid);
	printf("%s\t", group->gr_name);
}

void printf_time(time_t time){
	char *mytime = NULL;
	mytime = ctime(&time);
	char mtime[512] = {0};
    strncpy(mtime, mytime, strlen(mytime)-1);
	printf("%s\t",mtime);
}

void printf_filename(struct dirent * dir){
	printf("%s\n",dir->d_name);
}

void printf_size(int size){
	printf("%d\t",size);
}

void print(struct stat currentstat,struct dirent* currentdp){
	printf_perm(currentstat.st_mode);
	printf_link(currentstat.st_nlink);
	printf_usrname(currentstat.st_uid);
	printf_grname(currentstat.st_gid);
	printf_size(currentstat.st_size);
	printf_type(currentstat.st_mode);
	printf_time(currentstat.st_mtime);
	printf_filename(currentdp);
}

int loop(char *buffer){
	DIR *currentdir;
	struct dirent* currentdp;
	struct stat currentstat;
	//打开当前目录，并判断是否成功
	if ((currentdir=opendir(buffer))==NULL)
	{
		printf("open directory fail\n");
		return 0;
	}

	
	//读取当前目录下的目录项，并判断是否成功
	while((currentdp=readdir(currentdir))!=NULL)
	{
		if (currentdp->d_name[0] !='.')
		{
			//读取当前文件的信息，并判断是否成功
			if (lstat(buffer, &currentstat)!=0)
			{
				printf("get stat srror\n");
				continue;
			}

			if(currentdp->d_type!=4){
				pid_t pid_child,pid_return;
				pid_child = fork();
				if(pid_child<0){
					printf("erroe occured on forking.\n");
				}
				else if(pid_child == 0){
					char str[80];
					strcpy (str,buffer);
					strcat(str,"/");
					strcat (str,currentdp->d_name);
					execl("/home/mi/ox/2/mycp","mycp",str,"/home/mi/datian/",NULL);
				}
				do
				{
					pid_return = waitpid(pid_child,NULL,WNOHANG);
					if(pid_return == 0){
						sleep(1);
					}
				}
				while(pid_return==0);
				if(pid_return == pid_child){
				}
				else {
					printf("some error occured\n");
				}
			}
			else{
				char source[100];
				strcpy(source, buffer);
				strcat(source, "/");
				strcat(source, currentdp->d_name);
				char* mybuffer = source;
				loop(mybuffer);
			}
			print(currentstat,currentdp);
		}

	}
	closedir(currentdir);
}

int main(int argc, char* argv[]){
	char *buffer=NULL;
	buffer=(char *)(malloc(100*sizeof(char)));
	DIR *currentdir;
	struct dirent* currentdp;
	struct stat currentstat;

	if(argc==2){
		buffer = argv[1];
		printf("遍历的目录是：%s\n",buffer);
	}

	//getcwd()会将当前工作目录的绝对路径复制到参数buffer所指的内存空间中,参数maxlen为buffer的空间大小
	else if (getcwd(buffer,100*sizeof(char))!=NULL)
		printf("遍历的目录是：%s\n", buffer);

	loop(buffer);

	return 0;
	
}